home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / mach / ds3100.md / machCode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-09  |  54.5 KB  |  1,979 lines

  1. /* 
  2.  * machCode.c --
  3.  *
  4.  *         C code for the mach module.
  5.  *
  6.  *    Copyright (C) 1989 Digital Equipment Corporation.
  7.  *    Permission to use, copy, modify, and distribute this software and
  8.  *    its documentation for any purpose and without fee is hereby granted,
  9.  *    provided that the above copyright notice appears in all copies.  
  10.  *    Digital Equipment Corporation makes no representations about the
  11.  *    suitability of this software for any purpose.  It is provided "as is"
  12.  *    without express or implied warranty.
  13.  */
  14.  
  15. #ifndef lint
  16. static char rcsid[] = "$Header: /sprite/src/kernel/mach/ds3100.md/RCS/machCode.c,v 9.22 91/08/09 16:08:43 shirriff Exp $ SPRITE (DECWRL)";
  17. #endif not lint
  18.  
  19. #include <sprite.h>
  20. #include <stddef.h>
  21. #include <assert.h>
  22.  
  23. #include <machConst.h>
  24. #include <machMon.h>
  25. #include <machInt.h>
  26. #include <mach.h>
  27. #include <sys.h>
  28. #include <sync.h>
  29. #include <dbg.h>
  30. #include <proc.h>
  31. #include <procMigrate.h>
  32. #include <procUnixStubs.h>
  33. #include <sched.h>
  34. #include <vm.h>
  35. #include <vmMach.h>
  36. #include <sig.h>
  37. #include <sigMach.h>
  38. #include <swapBuffer.h>
  39. #include <net.h>
  40. #include <ultrixSignal.h>
  41.  
  42. /*
  43.  * Flag to set for new Unix compatiblity code.  Once the new
  44.  * code is working well enough, this flag should  be eliminated
  45.  * and the old compatibility code in machAsm.s, machUNIXSyscall.c etc.
  46.  * can be deleted.
  47.  */
  48.  
  49. int machNewUnixCompat;
  50.  
  51. /*
  52.  * Conversion of function to an unsigned value.
  53.  */
  54. #define F_TO_A    (Address)(unsigned)(int (*)())
  55. /*
  56.  *  Number of processors in the system.
  57.  */
  58. #ifndef NUM_PROCESSORS
  59. #define NUM_PROCESSORS 1
  60. #endif
  61.  
  62. int mach_NumProcessors = NUM_PROCESSORS;
  63.  
  64. /*
  65.  * TRUE if cpu was in kernel mode before the interrupt, FALSE if was in 
  66.  * user mode.
  67.  */
  68. Boolean    mach_KernelMode;
  69.  
  70. /*
  71.  *  Flag used by routines to determine if they are running at
  72.  *  interrupt level.
  73.  */
  74. Boolean mach_AtInterruptLevel = FALSE;
  75.  
  76. /*
  77.  * The machine type string is imported by the file system and
  78.  * used when expanding $MACHINE in file names.
  79.  */
  80.  
  81. char *mach_MachineType = "ds3100";
  82.  
  83. extern int debugProcStubs;
  84.  
  85. /*
  86.  * The byte ordering/alignment type used with Fmt_Convert and I/O control data
  87.  */
  88. Fmt_Format mach_Format = FMT_MIPS_FORMAT;
  89.  
  90. /*
  91.  *  Count of number of ``calls'' to enable interrupts minus number of calls
  92.  *  to disable interrupts.  Kept on a per-processor basis.
  93.  */
  94. int mach_NumDisableInterrupts[NUM_PROCESSORS];
  95. int *mach_NumDisableIntrsPtr = mach_NumDisableInterrupts;
  96.  
  97. /*
  98.  * The format that the kernel stack has to be in to start a process off.
  99.  */
  100. typedef struct {
  101.     int        magicNumber;        /* Magic number used to determine if
  102.                      * the stack has been corrupted. */
  103.     int        statusReg;        /* The status register value. */
  104.     int        filler[10];        /* Extra space on the stack to
  105.                      * store args and such. */
  106. } KernelStack;
  107.  
  108. /*
  109.  * The format of a signal stack that is pushed onto a user's stack when
  110.  * a signal is handled.
  111.  */
  112. typedef struct {
  113.     Sig_Stack    sigStack;
  114.     Sig_Context    sigContext;
  115. } SignalStack;
  116.  
  117. /*
  118.  * Machine dependent variables.
  119.  */
  120. Address    mach_KernStart;
  121. Address    mach_CodeStart;
  122. Address    mach_StackBottom;
  123. int    mach_KernStackSize;
  124. Address    mach_KernEnd;
  125. Address    mach_FirstUserAddr;
  126. Address    mach_LastUserAddr;
  127. Address    mach_MaxUserStackAddr;
  128. int    mach_LastUserStackPage;
  129.  
  130. /*
  131.  * The variables and tables below are used to dispatch kernel calls.
  132.  */
  133.  
  134. #define MAXCALLS 120
  135. #define MAXARGS  10
  136.  
  137. int machMaxSysCall;            /* Highest defined system call. */
  138. /*
  139.  * Tables to determine where to go to fetch the arguments for a system call.
  140.  */
  141. ReturnStatus (*machArgDispatch[MAXCALLS])();
  142. ReturnStatus (*machArgDispatchTable[])() = {
  143.     MachFetch0Args,
  144.     MachFetch0Args,
  145.     MachFetch0Args,
  146.     MachFetch0Args,
  147.     MachFetch0Args,
  148.     MachFetch1Arg,
  149.     MachFetch2Args,
  150.     MachFetch3Args,
  151.     MachFetch4Args,
  152.     MachFetch5Args,
  153.     MachFetch6Args,
  154. };
  155.  
  156. ReturnStatus (*(mach_NormalHandlers[MAXCALLS]))();
  157.                     /* For each system call, gives the
  158.                      * address of the routine to handle
  159.                      * the call for non-migrated processes.
  160.                      */
  161. ReturnStatus (*(mach_MigratedHandlers[MAXCALLS]))();
  162.                     /* For each system call, gives the
  163.                      * address of the routine to handle
  164.                      * the call for migrated processes. */
  165. int machKcallTableOffset;        /* Byte offset of the kcallTable field
  166.                      * in a Proc_ControlBlock. */
  167. int machStatePtrOffset;            /* Byte offset of the machStatePtr
  168.                      * field in a Proc_ControlBlock. */
  169. int machSpecialHandlingOffset;        /* Byte offset of the specialHandling
  170.                      * field in a Proc_ControlBlock. */
  171. MachStringTable    machMonBootParam;    /* Parameters from boot line. */
  172. /* 
  173.  * Pointer to the state structure for the current process and the
  174.  * current owner of the floating point unit.
  175.  */
  176. Mach_State    *machCurStatePtr = (Mach_State *)NIL;
  177. Mach_State    *machFPCurStatePtr = (Mach_State *)NIL;
  178.  
  179. extern Boolean Dev_SIIIntr();
  180. extern void Timer_TimerServiceInterrupt();
  181. extern void Dev_DC7085Interrupt();
  182. extern void MachFPInterrupt();
  183.  
  184. extern void PrintError _ARGS_((void));
  185. static void PrintInst _ARGS_((unsigned pc, unsigned inst));
  186. static void SoftFPReturn _ARGS_((void));
  187. static void MemErrorInterrupt _ARGS_((void));
  188.  
  189. /*
  190.  * The interrupt handler table. This originally was static, hence the
  191.  * initialization here.  It is now possible to set the entries
  192.  * via Mach_SetHandler().
  193.  */
  194. void (*machInterruptRoutines[MACH_NUM_HARD_INTERRUPTS])() = {
  195.     (void (*)())Dev_SIIIntr,
  196.     (void (*)())Net_Intr,
  197.     Dev_DC7085Interrupt,
  198.     Timer_TimerServiceInterrupt,
  199.     MemErrorInterrupt,
  200.     MachFPInterrupt,
  201. };
  202.  
  203. ClientData    machInterruptArgs[MACH_NUM_HARD_INTERRUPTS];
  204.  
  205. extern void Mach_KernGenException();
  206. extern void Mach_UserGenException();
  207. extern void VmMach_KernTLBException();
  208. extern void VmMach_TLBModException();
  209. extern void VmMach_UTLBMiss();
  210. extern void VmMach_EndUTLBMiss();
  211.  
  212. /*
  213.  * The kernel exception handlers.
  214.  */
  215. void (*machKernExcTable[])() = {
  216.     Mach_KernGenException,
  217.     VmMach_TLBModException,
  218.     VmMach_KernTLBException,
  219.     VmMach_KernTLBException,
  220.     Mach_KernGenException,
  221.     Mach_KernGenException,
  222.     Mach_KernGenException,
  223.     Mach_KernGenException,
  224.     Mach_KernGenException,
  225.     Mach_KernGenException,
  226.     Mach_KernGenException,
  227.     Mach_KernGenException,
  228.     Mach_KernGenException,
  229. };
  230.  
  231. /*
  232.  * The kernel exception handlers.
  233.  */
  234. void (*machUserExcTable[])() = {
  235.     Mach_UserGenException,
  236.     VmMach_TLBModException,
  237.     Mach_UserGenException,
  238.     Mach_UserGenException,
  239.     Mach_UserGenException,
  240.     Mach_UserGenException,
  241.     Mach_UserGenException,
  242.     Mach_UserGenException,
  243.     MachSysCall,
  244.     Mach_UserGenException,
  245.     Mach_UserGenException,
  246.     Mach_UserGenException,
  247.     Mach_UserGenException,
  248. };
  249.  
  250. /*
  251.  * Size of the instruction and data caches.
  252.  */
  253. unsigned    machDataCacheSize;
  254. unsigned    machInstCacheSize;
  255.  
  256. /*
  257.  * The debugger structure.
  258.  */
  259. Mach_DebugState    mach_DebugState;
  260. Mach_DebugState *machDebugStatePtr = &mach_DebugState;
  261.  
  262. static void SetupSigHandler _ARGS_((register Proc_ControlBlock *procPtr, 
  263.             register SignalStack *sigStackPtr, Address pc));
  264. static void ReturnFromSigHandler _ARGS_((register Proc_ControlBlock *procPtr));
  265. static ReturnStatus Interrupt _ARGS_((unsigned statusReg, unsigned causeReg, 
  266.             Address pc));
  267.  
  268. /*
  269.  * Preallocate all machine state structs.
  270.  */
  271. Mach_State    machStateTable[VMMACH_MAX_KERN_STACKS];
  272. int        nextStateIndex = 0;
  273.  
  274. /*
  275.  *  Save the bad address that caused an exception. This makes debugging
  276.  *  of TLB misses easier.
  277.  */
  278.  
  279. Address        machBadVaddr = (Address) NIL;
  280.  
  281.  
  282. /*
  283.  * ----------------------------------------------------------------------------
  284.  *
  285.  * Mach_Init --
  286.  *
  287.  *    Initialize the exception vector table and some of the dispatching
  288.  *    tables.
  289.  *
  290.  * Results:
  291.  *    None.
  292.  *
  293.  * Side effects:
  294.  *    The exception vector table is initialized.
  295.  *
  296.  * ----------------------------------------------------------------------------
  297.  */
  298. void
  299. Mach_Init(boot_argc,boot_argv)
  300. int    boot_argc;    /* Argc from boot sequence. */
  301. MachStringTable    *boot_argv;    /* Boot sequence strings. */
  302. {
  303.     extern char end[], edata[];
  304.     int offset, i;
  305.     char buf[256];
  306.  
  307.     /*
  308.      * Zero out the bss segment.
  309.      */
  310.     bzero(edata, end - edata);
  311.  
  312.     /*
  313.      * Set exported machine dependent variables.
  314.      */
  315.     mach_KernStart = (Address)MACH_KERN_START;
  316.     mach_KernEnd = (Address)MACH_KERN_END;
  317.     mach_CodeStart = (Address)MACH_CODE_START;
  318.     mach_StackBottom = (Address)MACH_STACK_BOTTOM;
  319.     mach_KernStackSize = MACH_KERN_STACK_SIZE;
  320.     mach_FirstUserAddr = (Address)MACH_FIRST_USER_ADDR;
  321.     mach_LastUserAddr = (Address)MACH_LAST_USER_ADDR;
  322.     mach_MaxUserStackAddr = (Address)MACH_MAX_USER_STACK_ADDR;
  323.     mach_LastUserStackPage = (MACH_MAX_USER_STACK_ADDR - 1) / VMMACH_PAGE_SIZE;
  324.  
  325.     /*
  326.      * Copy the boot parameter structure. The original location will get
  327.      * unmapped during vm initialization so we need to get our own copy.
  328.      * Depending on how the machine was booted, the boot arguments 
  329.      * may or may not be parsed.  So we'll glob them all together and
  330.      * then parse them.
  331.      */
  332.     buf[0] = '\0';
  333.     for (i = 0; i < boot_argc; i++) {
  334.     strcat(buf,boot_argv->argPtr[i]);
  335.     strcat(buf," ");
  336.     }
  337.     Mach_ArgParse(buf,&machMonBootParam);
  338.  
  339.     /*
  340.      * Initialize some of the dispatching information.  The rest is
  341.      * initialized by Mach_InitSysCall below.
  342.      */
  343.     machMaxSysCall = -1;
  344.     machKcallTableOffset = (int) &((Proc_ControlBlock *) 0)->kcallTable;
  345.     machStatePtrOffset = (int) &((Proc_ControlBlock *) 0)->machStatePtr;
  346.     machSpecialHandlingOffset = (int) 
  347.                 &((Proc_ControlBlock *) 0)->specialHandling;
  348.  
  349.     /*
  350.      * We start off with interrupts disabled.
  351.      */
  352.     mach_NumDisableInterrupts[0] = 1;
  353.  
  354.     /*
  355.      * Copy down exception vector code.
  356.      */
  357.     if (F_TO_A VmMach_EndUTLBMiss - F_TO_A VmMach_UTLBMiss > 0x80) {
  358.     panic("Mach_Init: UTLB code too large\n");
  359.     }
  360.     bcopy(F_TO_A VmMach_UTLBMiss, F_TO_A MACH_UTLB_MISS_EXC_VEC,
  361.         F_TO_A VmMach_EndUTLBMiss - F_TO_A VmMach_UTLBMiss);
  362.     bcopy(F_TO_A MachException, (Address)MACH_GEN_EXC_VEC,
  363.           F_TO_A MachEndException - F_TO_A MachException);
  364.  
  365.     /*
  366.      * Clear out the i and d caches.
  367.      */
  368.     Mach_MonPrintf("Configuring cache: ");
  369.     MachConfigCache();
  370.     Mach_MonPrintf("data cache size =%x inst cache size=%x\n",
  371.            machDataCacheSize, machInstCacheSize);
  372.     MachFlushCache();
  373. }
  374.  
  375. /*
  376.  * ----------------------------------------------------------------------------
  377.  *
  378.  * Mach_SetHandler --
  379.  *
  380.  *    Put a interrupt handling routine into the table.
  381.  *
  382.  * Results:
  383.  *     None.
  384.  *
  385.  * Side effects:
  386.  *     The interrupt handling table is modified.
  387.  *
  388.  * ----------------------------------------------------------------------------
  389.  */
  390.  
  391. void
  392. Mach_SetHandler(interruptNumber, handler, clientData)
  393.     int interruptNumber;    /* Interrupt number to set */
  394.     void (*handler)();    /* Interrupt handling procedure */
  395.     ClientData    clientData; /* ClientData for interrupt callback routine. */
  396. {
  397.     /*
  398.      * Check that it is valid.  Can't override FPU interrupt because it
  399.      * takes special parameters.
  400.      */
  401.     if ((interruptNumber < 0) || (interruptNumber >= MACH_NUM_HARD_INTERRUPTS)){
  402.     panic("Warning: Bad interrupt number %d\n",interruptNumber);
  403.     } else {
  404.     machInterruptRoutines[interruptNumber] = handler;
  405.     machInterruptArgs[interruptNumber] = clientData;
  406.     }
  407. }
  408.  
  409. static Vm_ProcInfo    mainProcInfo;
  410. static Mach_State    mainMachState;
  411. static VmMach_ProcData    mainProcData;
  412.  
  413. /*
  414.  *----------------------------------------------------------------------
  415.  *
  416.  * Mach_InitFirstProc --
  417.  *
  418.  *    Initialize the machine state struct for the very first process.
  419.  *
  420.  * Results:
  421.  *    None.
  422.  *
  423.  * Side effects:
  424.  *    Machine info allocated and stack start set up.
  425.  *
  426.  *----------------------------------------------------------------------
  427.  */
  428. void
  429. Mach_InitFirstProc(procPtr)
  430.     Proc_ControlBlock    *procPtr;
  431. {
  432.  
  433.     assert(offsetof(Proc_ControlBlock, unixErrno) == MACH_UNIX_ERRNO_OFFSET);
  434.     procPtr->machStatePtr = &mainMachState;
  435.     procPtr->machStatePtr->kernStackStart = mach_StackBottom;
  436.     procPtr->machStatePtr->kernStackEnd = 
  437.                 (mach_StackBottom + mach_KernStackSize);
  438.     /*
  439.      * Set up the TLB entries.  This code depends
  440.      * implictly upon MACH_KERN_STACK_PAGES.
  441.      */
  442.     procPtr->machStatePtr->tlbHighEntry  = 0;
  443.     procPtr->machStatePtr->tlbLowEntries[0] = 0;
  444.     procPtr->machStatePtr->tlbLowEntries[1] = 0;
  445.     procPtr->machStatePtr->tlbLowEntries[2] = 0;
  446.     procPtr->vmPtr = &mainProcInfo;
  447.     procPtr->vmPtr->machPtr = &mainProcData;
  448.     VmMach_ProcInit(&mainProcInfo);
  449.     machCurStatePtr = procPtr->machStatePtr;
  450.     VmMach_SetupContext(procPtr);
  451. }
  452.  
  453.  
  454. /*
  455.  *----------------------------------------------------------------------
  456.  *
  457.  * Mach_SetupNewState --
  458.  *
  459.  *    Initialize the machine state for this process.  This includes 
  460.  *    allocating and initializing a kernel stack.  Assumed that will
  461.  *    be called when starting a process after a fork or restarting a
  462.  *    process after a migration.
  463.  *
  464.  * Results:
  465.  *    PROC_NO_STACKS if couldn't allocate a kernel stack.  SUCCESS otherwise.
  466.  *
  467.  * Side effects:
  468.  *    Machine state in the destination process control block is overwritten.
  469.  *
  470.  *----------------------------------------------------------------------
  471.  */ 
  472. ReturnStatus
  473. Mach_SetupNewState(procPtr, fromStatePtr, startFunc, startPC, user)
  474.     Proc_ControlBlock    *procPtr;    /* Pointer to process control block
  475.                      * to initialize state for. */
  476.     Mach_State        *fromStatePtr;    /* State of parent on fork or from
  477.                      * other machine on migration. */
  478.     void        (*startFunc)();    /* Function to call when process first
  479.                      * starts executing. */
  480.     Address        startPC;    /* Address to pass as argument to 
  481.                      * startFunc.  If NIL then the address
  482.                      * is taken from *fromStatePtr's 
  483.                      * exception stack. */
  484.     Boolean        user;        /* TRUE if is a user process. */
  485. {
  486.     register    KernelStack    *stackPtr;
  487.     register    Mach_State    *statePtr;
  488.     unsigned            virtPage;
  489.  
  490.     if (procPtr->machStatePtr == (Mach_State *)NIL) {
  491.     procPtr->machStatePtr = &machStateTable[nextStateIndex];
  492.     nextStateIndex++;
  493.     if (nextStateIndex >= VMMACH_MAX_KERN_STACKS) {
  494.         panic("Mach_SetupNewState: Out of machine state structs\n");
  495.     }
  496.     }
  497.  
  498.     statePtr = procPtr->machStatePtr;
  499.     /* 
  500.      * Allocate a kernel stack for this process.
  501.      */
  502.     statePtr->kernStackStart = Vm_GetKernelStack(0);
  503.     if (statePtr->kernStackStart == (Address)NIL) {
  504.     return(PROC_NO_STACKS);
  505.     }
  506.     statePtr->kernStackEnd = statePtr->kernStackStart + MACH_KERN_STACK_SIZE;
  507.     /*
  508.      * Set up the TLB entries.  This code depends
  509.      * implictly upon MACH_KERN_STACK_PAGES.
  510.      */
  511.     virtPage = (unsigned)(statePtr->kernStackStart + VMMACH_PAGE_SIZE) >>
  512.                             VMMACH_PAGE_SHIFT;
  513.     statePtr->tlbHighEntry = (virtPage << VMMACH_TLB_VIRT_PAGE_SHIFT) |
  514.                  (VMMACH_KERN_PID << VMMACH_TLB_PID_SHIFT);
  515.     virtPage -= VMMACH_VIRT_CACHED_START_PAGE;
  516.     statePtr->tlbLowEntries[0] = vmMach_KernelTLBMap[virtPage];
  517.     statePtr->tlbLowEntries[1] = vmMach_KernelTLBMap[virtPage + 1];
  518.     statePtr->tlbLowEntries[2] = vmMach_KernelTLBMap[virtPage + 2];
  519.  
  520.     statePtr->switchRegState.regs[SP] =
  521.             (unsigned)(statePtr->kernStackEnd - sizeof(KernelStack));
  522.     /*
  523.      * Initialize the stack so that it looks like it is in the middle of
  524.      * Mach_ContextSwitch.
  525.      */
  526.     stackPtr = (KernelStack *)(statePtr->switchRegState.regs[SP]);
  527.     stackPtr->magicNumber = MAGIC;
  528.     stackPtr->statusReg = 0;
  529.     statePtr->switchRegState.regs[RA] = (unsigned)startFunc;
  530.     /*
  531.      * Set up the user's stack pointer.
  532.      */
  533.     statePtr->userState.regState.regs[SP] = (unsigned)mach_MaxUserStackAddr;
  534.     /* 
  535.      * Set up the state of the process.  User processes inherit from their
  536.      * parent or the migrated process.  If the PC is not specified, take it
  537.      * from the parent as well.
  538.      */
  539.     if (user) {
  540.     bcopy((Address)&fromStatePtr->userState,
  541.           (Address)&statePtr->userState,
  542.           sizeof(statePtr->userState));
  543.     statePtr->userState.regState.pc += 4;
  544.     }
  545.     if (startPC == (Address)NIL) {
  546.     statePtr->switchRegState.regs[A0] = 
  547.             (unsigned)fromStatePtr->userState.regState.pc + 4;
  548.     } else {
  549.     statePtr->switchRegState.regs[A0] = (unsigned)startPC;
  550.     }
  551.     statePtr->userState.regState.fpStatusReg = 0;
  552.  
  553.     return(SUCCESS);
  554. }
  555.  
  556. /*
  557.  *----------------------------------------------------------------------
  558.  *
  559.  * Mach_SetReturnVal --
  560.  *
  561.  *    Set the return value for a process from a system call.  Intended to
  562.  *    be called by the routine that starts a user process after a fork.
  563.  *
  564.  * Results:
  565.  *    None.
  566.  *
  567.  * Side effects:
  568.  *    Register D0 is set in the user registers.
  569.  *
  570.  *----------------------------------------------------------------------
  571.  */ 
  572. void
  573. Mach_SetReturnVal(procPtr, retVal, retVal2)
  574.     Proc_ControlBlock    *procPtr;    /* Process to set return value for. */
  575.     int            retVal;        /* Value for process to return. */
  576.     int            retVal2;    /* Second return value. */
  577. {
  578.     procPtr->machStatePtr->userState.regState.regs[V0] = (unsigned)retVal;
  579.     procPtr->machStatePtr->userState.regState.regs[V1] = (unsigned)retVal2;
  580. }
  581.  
  582. /*----------------------------------------------------------------------------
  583.  *
  584.  * Mach_Return2 --
  585.  *
  586.  *      Set the second return value for Unix compat. routines that
  587.  *      return two values.
  588.  *
  589.  * Results:
  590.  *      None.
  591.  *
  592.  * Side effects:
  593.  *      v1 <- val
  594.  *
  595.  *----------------------------------------------------------------------------
  596.  */
  597. void
  598. Mach_Return2(val)
  599. int val;
  600. {
  601.     Proc_GetActualProc()->machStatePtr->userState.regState.regs[V1] =
  602.         (unsigned)val;
  603. }
  604.  
  605. /*
  606.  *----------------------------------------------------------------------
  607.  *
  608.  * Mach_StartUserProc --
  609.  *
  610.  *    Start a user process executing for the first time.
  611.  *
  612.  * Results:
  613.  *    None.
  614.  *
  615.  * Side effects:
  616.  *    Stack pointer and the program counter set for the process and
  617.  *    the current process's image is replaced.
  618.  *
  619.  *----------------------------------------------------------------------
  620.  */
  621. void
  622. Mach_StartUserProc(procPtr, entryPoint)
  623.     Proc_ControlBlock    *procPtr;    /* Process control block for process
  624.                      * to start. */
  625.     Address        entryPoint;    /* Where process is to start
  626.                      * executing. */
  627. {
  628.     register    Mach_State    *statePtr;
  629.  
  630.     statePtr = procPtr->machStatePtr;
  631.     statePtr->userState.regState.pc = entryPoint;
  632.     (void)MachUserReturn(procPtr);
  633.  
  634.     MachRunUserProc(entryPoint, statePtr->userState.regState.regs[SP]);
  635.     /* THIS DOES NOT RETURN */
  636. }
  637.  
  638.  
  639. /*
  640.  *----------------------------------------------------------------------
  641.  *
  642.  * Mach_ExecUserProc --
  643.  *
  644.  *    Replace the calling user process's image with a new one.
  645.  *
  646.  * Results:
  647.  *    None.
  648.  *
  649.  * Side effects:
  650.  *    Stack pointer set for the process.
  651.  *
  652.  *----------------------------------------------------------------------
  653.  */
  654. void
  655. Mach_ExecUserProc(procPtr, userStackPtr, entryPoint)
  656.     Proc_ControlBlock    *procPtr;        /* Process control block for
  657.                          * process to exec. */
  658.     Address        userStackPtr;    /* Stack pointer for when the
  659.                          * user process resumes 
  660.                          * execution. */
  661.     Address        entryPoint;        /* Where the user process is
  662.                          * to resume execution. */
  663. {
  664.     procPtr->machStatePtr->userState.regState.regs[SP] =
  665.                         (unsigned)userStackPtr;
  666.     Mach_StartUserProc(procPtr, entryPoint);
  667.     /* THIS DOES NOT RETURN */
  668. }
  669.  
  670. /*
  671.  *----------------------------------------------------------------------
  672.  *
  673.  * Mach_FreeState --
  674.  *
  675.  *    Free up the machine state for the given process control block.
  676.  *
  677.  * Results:
  678.  *    None.
  679.  *
  680.  * Side effects:
  681.  *    Free up the kernel stack.
  682.  *
  683.  *----------------------------------------------------------------------
  684.  */
  685. void
  686. Mach_FreeState(procPtr)
  687.     Proc_ControlBlock    *procPtr;    /* Process control block to free
  688.                      * machine state for. */
  689. {
  690.     if (procPtr->machStatePtr->kernStackStart != (Address)NIL) {
  691.     Vm_FreeKernelStack(procPtr->machStatePtr->kernStackStart);
  692.     procPtr->machStatePtr->kernStackStart = (Address)NIL;
  693.     }
  694.     if (procPtr->machStatePtr == machFPCurStatePtr) {
  695.     machFPCurStatePtr = (Mach_State *)NIL;
  696.     }
  697. }
  698.  
  699.  
  700. /*
  701.  *----------------------------------------------------------------------
  702.  *
  703.  * Mach_CopyState --
  704.  *
  705.  *    Copy the state from the given state structure to the machine
  706.  *    state structure for the destination process control block.  Intended
  707.  *    to be used by the debugger to modify the state.The only fields
  708.  *    that can be modified are the following:
  709.  *
  710.  *        1) user stack pointer
  711.  *        2) all trap registers except for the stack pointer because the
  712.  *           stack pointer in the trap registers is the kernel stack pointer.
  713.  *        3) the PC, VOR and status register in the exception stack.
  714.  *
  715.  * Results:
  716.  *    None.
  717.  *
  718.  * Side effects:
  719.  *    Machine state in the destination process control block is overwritten.
  720.  *
  721.  *----------------------------------------------------------------------
  722.  */ 
  723. void
  724. Mach_CopyState(statePtr, destProcPtr)
  725.     Mach_State        *statePtr;    /* Pointer to state to copy from. */
  726.     Proc_ControlBlock    *destProcPtr;    /* Process control block to copy
  727.                      * state to. */
  728. {
  729.     bcopy((Address)&statePtr->userState,
  730.           (Address)&destProcPtr->machStatePtr->userState,
  731.           sizeof(statePtr->userState));
  732. }
  733.  
  734.  
  735. /*
  736.  *----------------------------------------------------------------------
  737.  *
  738.  * Mach_GetDebugState --
  739.  *
  740.  *    Extract the appropriate fields from the machine state struct
  741.  *    and store them into the debug struct.
  742.  *
  743.  * Results:
  744.  *    None.
  745.  *
  746.  * Side effects:
  747.  *    Debug struct filled in from machine state struct.
  748.  *
  749.  *----------------------------------------------------------------------
  750.  */ 
  751. void
  752. Mach_GetDebugState(procPtr, debugStatePtr)
  753.     Proc_ControlBlock    *procPtr;
  754.     Proc_DebugState    *debugStatePtr;
  755. {
  756.     register    Mach_State    *machStatePtr;
  757.  
  758.     machStatePtr = procPtr->machStatePtr;
  759.     bcopy((Address)machStatePtr->userState.regState.regs,
  760.           (Address)debugStatePtr->regState.regs,
  761.           sizeof(machStatePtr->userState.regState.regs));
  762.     debugStatePtr->regState.pc = machStatePtr->userState.regState.pc;
  763. }
  764.  
  765.  
  766. /*
  767.  *----------------------------------------------------------------------
  768.  *
  769.  * Mach_SetDebugState --
  770.  *
  771.  *    Extract the appropriate fields from the debug struct
  772.  *    and store them into the machine state struct.
  773.  *
  774.  * Results:
  775.  *    None.
  776.  *
  777.  * Side effects:
  778.  *    Machine state struct filled in from the debug state struct.
  779.  *
  780.  *----------------------------------------------------------------------
  781.  */ 
  782. void
  783. Mach_SetDebugState(procPtr, debugStatePtr)
  784.     Proc_ControlBlock    *procPtr;
  785.     Proc_DebugState    *debugStatePtr;
  786. {
  787.     register    Mach_State    *machStatePtr;
  788.  
  789.     machStatePtr = procPtr->machStatePtr;
  790.     bcopy((Address)debugStatePtr->regState.regs,
  791.           (Address)machStatePtr->userState.regState.regs,
  792.           sizeof(machStatePtr->userState.regState.regs));
  793.     machStatePtr->userState.regState.pc = debugStatePtr->regState.pc;
  794. }
  795.  
  796.  
  797. /*
  798.  * ----------------------------------------------------------------------------
  799.  *
  800.  * Mach_GetUserStackPtr --
  801.  *
  802.  *    Return the user stack pointer from the machine state struct for the
  803.  *    given process.
  804.  *
  805.  * Results:
  806.  *    The value of the user stack pointer when the process trapped.
  807.  *
  808.  * Side effects:
  809.  *    None.
  810.  *
  811.  * ----------------------------------------------------------------------------
  812.  */
  813. Address
  814. Mach_GetUserStackPtr(procPtr)
  815.     Proc_ControlBlock    *procPtr;
  816. {
  817.     return((Address)procPtr->machStatePtr->userState.regState.regs[SP]);
  818. }
  819.  
  820.  
  821. /*
  822.  * ----------------------------------------------------------------------------
  823.  *
  824.  * Mach_GetStackPointer --
  825.  *
  826.  *    Return the value of the stack pointer.
  827.  *
  828.  * Results:
  829.  *    The value of the user's stack pointer.
  830.  *
  831.  * Side effects:
  832.  *    None.
  833.  *
  834.  * ----------------------------------------------------------------------------
  835.  */
  836. Address
  837. Mach_GetStackPointer(procPtr)
  838.     Proc_ControlBlock    *procPtr;
  839. {
  840.     return((Address)procPtr->machStatePtr->userState.regState.regs[SP]);
  841. }
  842.  
  843.  
  844. /*
  845.  *----------------------------------------------------------------------
  846.  *
  847.  * Mach_InitSyscall --
  848.  *
  849.  *    During initialization, this procedure is called once for each
  850.  *    kernel call, in order to set up information used to dispatch
  851.  *    the kernel call.  This procedure must be called once for each
  852.  *    kernel call, in order starting at 0.
  853.  *
  854.  * Results:
  855.  *    None.
  856.  *
  857.  * Side effects:
  858.  *    Initializes the dispatch tables for the kernel call.
  859.  *
  860.  *----------------------------------------------------------------------
  861.  */
  862. void
  863. Mach_InitSyscall(callNum, numArgs, normalHandler, migratedHandler)
  864.     int callNum;            /* Number of the system call. */
  865.     int numArgs;            /* Number of one-word arguments passed
  866.                      * into call on stack. */
  867.     ReturnStatus (*normalHandler)();    /* Procedure to process kernel call
  868.                      * when process isn't migrated. */
  869.     ReturnStatus (*migratedHandler)();    /* Procedure to process kernel call
  870.                      * for migrated processes. */
  871. {
  872.     machMaxSysCall++;
  873.     if (machMaxSysCall != callNum) {
  874.     printf("Warning: out-of-order kernel call initialization, call %d\n",
  875.            callNum);
  876.     }
  877.     if (machMaxSysCall >= MAXCALLS) {
  878.     printf("Warning: too many kernel calls.\n");
  879.     machMaxSysCall--;
  880.     return;
  881.     }
  882.     if (numArgs > MAXARGS) {
  883.     printf("Warning: too many arguments to kernel call %d\n", callNum);
  884.     numArgs = MAXARGS;
  885.     }
  886.     machArgDispatch[machMaxSysCall] = machArgDispatchTable[numArgs];
  887.     mach_NormalHandlers[machMaxSysCall] = normalHandler;
  888.     mach_MigratedHandlers[machMaxSysCall] = migratedHandler;
  889. }
  890.  
  891.  
  892. /*
  893.  * ----------------------------------------------------------------------------
  894.  *
  895.  * MachUserExceptionHandler --
  896.  *
  897.  *      Handle a user exception.
  898.  *
  899.  * Results:
  900.  *      TRUE if should enable the floating point coprocessor.
  901.  *
  902.  * Side effects:
  903.  *      None.
  904.  *
  905.  * ----------------------------------------------------------------------------
  906.  */
  907. Boolean
  908. MachUserExceptionHandler(statusReg, causeReg, badVaddr, pc)
  909.     unsigned    statusReg;    /* The status register at the time of the
  910.                  * exception. */
  911.     unsigned    causeReg;    /* The cause register - contains the type
  912.                  * of exception. */
  913.     Address    badVaddr;    /* The address (if any) that the fault
  914.                  * occured on. */
  915.     Address    pc;        /* Program counter where to continue. */
  916. {
  917.     register    Proc_ControlBlock    *procPtr;
  918.     int                    cause;
  919.     Boolean                retVal;
  920.     ReturnStatus            status;
  921.  
  922.     machBadVaddr = badVaddr;
  923.     cause = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
  924.     if (cause != MACH_EXC_INT) {
  925.     Mach_EnableIntr();
  926.     }
  927.  
  928.     procPtr = Proc_GetActualProc();
  929.     switch (cause) {
  930.     case MACH_EXC_INT:
  931.         status = Interrupt(statusReg, causeReg, pc);
  932.         if (status != MACH_OK) {
  933.         panic("MachUserExceptionHandler: nested interrupts.\n");
  934.         }
  935.         /* 
  936.          * Enable interrupts so that we can do the user mode return
  937.          * checks.
  938.          */
  939.         Mach_EnableIntr();
  940.         break;
  941.     case MACH_EXC_TLB_MOD:
  942.         if (VmMach_TLBModFault(badVaddr) != SUCCESS) {
  943.         printf("Protection fault in process %x: pc=%x addr=%x\n",
  944.             procPtr->processID, pc, badVaddr);
  945.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  946.                 procPtr->processID, FALSE, badVaddr);
  947.         }
  948.         break;
  949.     case MACH_EXC_TLB_LD_MISS:
  950.     case MACH_EXC_TLB_ST_MISS:
  951.         if (VmMach_TLBFault(badVaddr) != SUCCESS) {
  952.         printf("Bad user TLB fault in process %x: pc=%x addr=%x\n",
  953.             procPtr->processID, pc, badVaddr);
  954.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  955.                 procPtr->processID, FALSE, badVaddr);
  956.         }
  957.         break;
  958.     case MACH_EXC_ADDR_ERR_LD:
  959.     case MACH_EXC_ADDR_ERR_ST:
  960.         printf("Address fault in process %x: pc=%x addr=%x\n",
  961.             procPtr->processID, pc, badVaddr);
  962.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  963.                 procPtr->processID, FALSE, badVaddr);
  964.         break;
  965.     case MACH_EXC_BUS_ERR_IFETCH:
  966.         printf("MachExceptionHandler: User bus error on ifetch");
  967.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  968.                 procPtr->processID, FALSE, badVaddr);
  969.         break;
  970.     case MACH_EXC_BUS_ERR_LD_ST:
  971.         printf("MachExceptionHandler: User bus error on ld or st");
  972.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  973.                 procPtr->processID, FALSE, badVaddr);
  974.         break;
  975.     case MACH_EXC_SYSCALL:
  976.         if (!MachUNIXSyscall()) {
  977.         printf("MachExceptionHandler: Bad syscall magic for proc %x\n",
  978.                             procPtr->processID);
  979.         (void) Sig_Send(SIG_ILL_INST, SIG_BAD_TRAP,
  980.                 procPtr->processID, FALSE, pc);
  981.         }
  982.         break;
  983.     case MACH_EXC_BREAK: {
  984.         unsigned inst;
  985.         /*
  986.          * Check to see if this is a return from signal handler
  987.          * break or a normal breakpoint.
  988.          */
  989.         if (Vm_CopyIn(sizeof(int), pc, (Address)&inst) != SUCCESS) {
  990.         panic("MachExceptionHandler: Couldn't fetch break inst.");
  991.         }
  992. #if 0
  993.         printf("Pc = 0x%x, Instruction = 0x%x\n", pc, inst);
  994.         printf("Cause register = 0x%x\n", causeReg);
  995. #endif
  996.         switch ((int)(inst & MACH_BREAK_CODE_FIELD)) {
  997.         case MACH_BREAKPOINT_VAL:
  998.             Proc_Lock(procPtr);
  999.             if (procPtr->genFlags & PROC_DEBUG_ON_EXEC) {
  1000.             procPtr->genFlags &= ~PROC_DEBUG_ON_EXEC;
  1001.             (void) Sig_SendProc(procPtr, SIG_DEBUG, 
  1002.                         SIG_NO_CODE, pc);
  1003.             } else {
  1004.             (void) Sig_SendProc(procPtr, SIG_BREAKPOINT, 
  1005.                         SIG_NO_CODE, pc);
  1006.             }
  1007.             Proc_Unlock(procPtr);
  1008.             break;
  1009.         case MACH_SSTEP_VAL: {
  1010.             ReturnStatus    status;
  1011.  
  1012.             Vm_ChangeCodeProt(procPtr, pc, 4, TRUE);
  1013.             status = Vm_CopyOut(4, (Address)&machCurStatePtr->sstepInst,                    pc);
  1014.             Vm_ChangeCodeProt(procPtr, pc, 4, FALSE);
  1015.             Vm_FlushCode(procPtr, pc, 4);
  1016.             if (status != SUCCESS) {
  1017.             panic("MachUserExceptionHandler: Bad sstep PC\n");
  1018.             }
  1019.             Proc_Lock(procPtr);
  1020.             (void) Sig_SendProc(procPtr, SIG_TRACE_TRAP, SIG_NO_CODE,
  1021.                 pc);
  1022.             Proc_Unlock(procPtr);
  1023.             break;
  1024.         }
  1025.  
  1026.         case MACH_SIG_RET_VAL:
  1027.             ReturnFromSigHandler(procPtr);
  1028.             break;
  1029.         default:
  1030.             printf("Bogus bp-trap\n");
  1031.             (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1032.                     procPtr->processID, FALSE, pc);
  1033.             break;
  1034.         }
  1035.         break;
  1036.     }
  1037.     case MACH_EXC_RES_INST:
  1038.         printf("Reserved instruction in process %x at pc=%x\n",
  1039.             procPtr->processID, pc);
  1040.         (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1041.                 procPtr->processID, FALSE, pc);
  1042.         break;
  1043.     case MACH_EXC_COP_UNUSABLE:
  1044.         MachSwitchFPState(machFPCurStatePtr, machCurStatePtr);
  1045.         machFPCurStatePtr = machCurStatePtr;
  1046.         break;
  1047.     case MACH_EXC_OVFLOW:
  1048.         printf("Overflow exception in process %x at pc=%x\n",
  1049.             procPtr->processID, pc);
  1050.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_OVERFLOW,
  1051.                 procPtr->processID, FALSE, pc);
  1052.         break;
  1053.     }
  1054.     retVal = MachUserReturn(procPtr);
  1055.  
  1056.     return(retVal);
  1057. }
  1058.  
  1059.  
  1060. /*
  1061.  * ----------------------------------------------------------------------------
  1062.  *
  1063.  * MachKernelExceptionHandler --
  1064.  *
  1065.  *      Handle a kernel exception.
  1066.  *
  1067.  * Results:
  1068.  *      MACH_KERN_ERROR if the debugger should be called after this routine 
  1069.  *    returns, MACH_USER_ERROR if a copy to/from user space caused an 
  1070.  *    unrecoverable bus error, and MACH_OK if everything worked out ok.
  1071.  *
  1072.  * Side effects:
  1073.  *      None.
  1074.  *
  1075.  * ----------------------------------------------------------------------------
  1076.  */
  1077. int
  1078. MachKernelExceptionHandler(statusReg, causeReg, badVaddr, pc)
  1079.     unsigned    statusReg;    /* The status register at the time of the
  1080.                  * exception. */
  1081.     unsigned    causeReg;    /* The cause register - contains the type
  1082.                  * of exception. */
  1083.     Address    badVaddr;    /* The address (if any) that the fault
  1084.                  * occured on. */
  1085.     Address    pc;        /* Program counter where to continue. */
  1086. {
  1087.     register    Proc_ControlBlock    *procPtr;
  1088.     ReturnStatus            status;
  1089.     int                    cause;
  1090.  
  1091.     cause = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
  1092.     machBadVaddr = badVaddr;
  1093.  
  1094.     /*
  1095.      * Process kernel traps.
  1096.      */
  1097.     procPtr = Proc_GetActualProc();
  1098.     switch (cause) {
  1099.     case MACH_EXC_INT:
  1100.         status = Interrupt(statusReg, causeReg, pc);
  1101.         return(status);
  1102.     case MACH_EXC_TLB_LD_MISS:
  1103.     case MACH_EXC_TLB_ST_MISS:
  1104.     case MACH_EXC_TLB_MOD: {
  1105.         Boolean    copyInProgress = FALSE;
  1106.  
  1107.         if (statusReg & MACH_SR_INT_ENA_PREV) {
  1108.         /*
  1109.          * Enable interrupts.
  1110.          */
  1111.         Mach_EnableIntr();
  1112.         }
  1113.  
  1114.         if (pc >= F_TO_A Vm_CopyIn && pc < F_TO_A VmMachCopyEnd) {
  1115.         copyInProgress = TRUE;
  1116.         } else if (pc >= F_TO_A MachFetchArgs &&
  1117.                    pc <= F_TO_A MachFetchArgsEnd) {
  1118.         copyInProgress = TRUE;
  1119.         } else if (badVaddr < (Address)VMMACH_VIRT_CACHED_START &&
  1120.                (badVaddr >= (Address)VMMACH_PHYS_CACHED_START ||
  1121.             procPtr == (Proc_ControlBlock *)NIL ||
  1122.             procPtr->vmPtr->numMakeAcc == 0)) {
  1123.         if (procPtr != (Proc_ControlBlock *)NIL) {
  1124.             printf("procPtr->vmPtr->numMakeAcc = %d\n", 
  1125.             procPtr->vmPtr->numMakeAcc);
  1126.         }
  1127.         return(MACH_KERN_ERROR);
  1128.         }
  1129.         if (((causeReg & MACH_CR_EXC_CODE) >> 
  1130.             MACH_CR_EXC_CODE_SHIFT) == MACH_EXC_TLB_MOD) {
  1131.         status = VmMach_TLBModFault(badVaddr);
  1132.         } else {
  1133.         status = VmMach_TLBFault(badVaddr);
  1134.         }
  1135.         if (status != SUCCESS) {
  1136.         if (copyInProgress) {
  1137.             return(MACH_USER_ERROR);
  1138.         } else {
  1139.             printf("badVaddr = 0x%x\n", badVaddr);
  1140.             return(MACH_KERN_ERROR);
  1141.         }
  1142.         } else {
  1143.         return(MACH_OK);
  1144.         }
  1145.     }
  1146.  
  1147.     case MACH_EXC_ADDR_ERR_LD:
  1148.         printf("MachKernelExceptionHandler: %s: addr: %x PC: %x\n",
  1149.             "Address error on load", badVaddr, pc);
  1150.         return(MACH_KERN_ERROR);
  1151.     case MACH_EXC_ADDR_ERR_ST:
  1152.         printf("MachKernelExceptionHandler:  Address error on store\n");
  1153.         return(MACH_KERN_ERROR);
  1154.     case MACH_EXC_BUS_ERR_IFETCH:
  1155.         printf("MachKernelExceptionHandler:  Bus error on ifetch\n");
  1156.         return(MACH_KERN_ERROR);
  1157.     case MACH_EXC_BUS_ERR_LD_ST:
  1158.         if (pc >= F_TO_A Mach_Probe &&
  1159.             pc <= F_TO_A MachProbeEnd) {
  1160.         return(MACH_USER_ERROR);
  1161.         }
  1162.         printf("MachKernelExceptionHandler:  Bus error on load or store\n");
  1163.         return(MACH_KERN_ERROR);
  1164.     case MACH_EXC_SYSCALL:
  1165.         printf("MachKernelExceptionHandler:  System call in kernel mode\n");
  1166.         return(MACH_KERN_ERROR);
  1167.     case MACH_EXC_BREAK:
  1168.         return(MACH_KERN_ERROR);
  1169.     case MACH_EXC_RES_INST:
  1170.         printf("MachKernelExceptionHandler:  Reserved instruction\n");
  1171.         return(MACH_KERN_ERROR);
  1172.     case MACH_EXC_COP_UNUSABLE:
  1173.         printf("MachKernelExceptionHandler:  Coprocessor unusable\n");
  1174.         return(MACH_KERN_ERROR);
  1175.     case MACH_EXC_OVFLOW:
  1176.         printf("MachKernelExceptionHandler:  Overflow\n");
  1177.         return(MACH_KERN_ERROR);
  1178.     default:
  1179.         printf("MachKernelExceptionHandler: Unknown exception\n");
  1180.         return(MACH_KERN_ERROR);
  1181.     }
  1182. }
  1183.  
  1184.  
  1185. /*
  1186.  * ----------------------------------------------------------------------------
  1187.  *
  1188.  * Interrupt --
  1189.  *
  1190.  *      Call the proper interrupt handler for the given interrupt.
  1191.  *
  1192.  * Results:
  1193.  *      MACH_KERN_ERROR if the machine should go into the debugger, or MACH_OK
  1194.  *    otherwise.
  1195.  *
  1196.  * Side effects:
  1197.  *      None.
  1198.  *
  1199.  * ----------------------------------------------------------------------------
  1200.  */
  1201. #define DEBUG_INTR
  1202. #ifdef DEBUG_INTR
  1203. static int lastInterruptCalled = -1;
  1204. #endif  /* DEBUG_INTR */
  1205.  
  1206.  
  1207. static ReturnStatus
  1208. Interrupt(statusReg, causeReg, pc)
  1209.     unsigned    statusReg;
  1210.     unsigned    causeReg;
  1211.     Address    pc;
  1212. {
  1213.     int        n;
  1214.     unsigned    mask;
  1215.  
  1216. #ifdef DEBUG_INTR
  1217.     if (mach_AtInterruptLevel) {
  1218.     printf("Received interrupt while at interrupt level.\n");
  1219.     }
  1220.     if (mach_NumDisableIntrsPtr[0] > 0) {
  1221.     printf("Received interrupt with mach_NumDisableIntrsPtr[0] = %d.\n",
  1222.            mach_NumDisableIntrsPtr[0]);
  1223.     }
  1224. #endif /* DEBUG_INTR */
  1225.     
  1226.     mach_KernelMode = !(statusReg & MACH_SR_KU_PREV);
  1227.     mach_AtInterruptLevel = 1;
  1228.     n = 0;
  1229.     mask = (causeReg & statusReg & MACH_CR_INT_PENDING) >> 
  1230.                         MACH_CR_HARD_INT_SHIFT;
  1231.     while (mask != 0) {
  1232.     if (mask & 1) {
  1233. #ifdef DEBUG_INTR
  1234.         if (n >= MACH_NUM_HARD_INTERRUPTS) {
  1235.         printf("Bogus index (%d) for interrupt handler\n", n);
  1236.         mach_AtInterruptLevel = 0;
  1237.         return(MACH_KERN_ERROR);
  1238.         }
  1239.         lastInterruptCalled = n;
  1240. #endif /* DEBUG_INTR */
  1241.     /*
  1242.      * Interrupt 5, the FPU interrupt, requires the status, cause, and pc.
  1243.      * These values may have changed in the registers, during a call to
  1244.      * another interrupt handler, so we have to hand the routine the original
  1245.      * values.
  1246.      *
  1247.      * Interrupt 3, the timer interrupt, requires this stuff too, so it
  1248.      * can record the pc for profiling.
  1249.      */
  1250.         if (n == 3 || n==5) {
  1251.         machInterruptRoutines[n](statusReg, causeReg, pc);
  1252.         } else {
  1253.         machInterruptRoutines[n](machInterruptArgs[n]);
  1254.         }
  1255.     }
  1256.     mask >>= 1;
  1257.     n++;
  1258.     }
  1259.  
  1260.     mach_AtInterruptLevel = 0;
  1261. #ifdef DEBUG_INTR
  1262.     lastInterruptCalled = -1;
  1263. #endif /* DEBUG_INTR */
  1264.     return(MACH_OK);
  1265. }
  1266.  
  1267. /*
  1268.  * ----------------------------------------------------------------------------
  1269.  *
  1270.  * MachUserReturn --
  1271.  *
  1272.  *      Take the proper action to return from a user exception.
  1273.  *
  1274.  * Results:
  1275.  *      None.
  1276.  *
  1277.  * Side effects:
  1278.  *      Interrupts disabled.
  1279.  *
  1280.  * ----------------------------------------------------------------------------
  1281.  */
  1282. Boolean
  1283. MachUserReturn(procPtr)
  1284.     register    Proc_ControlBlock    *procPtr;
  1285. {
  1286.     SignalStack    sigStack;
  1287.     Address    pc;
  1288.     int        restarted = 0;
  1289.  
  1290.  
  1291.     if (procPtr->Prof_Scale >= 2 && procPtr->Prof_PC != 0) {
  1292.     Prof_RecordPC(procPtr);
  1293.     }
  1294.  
  1295.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1296.         procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1297.     printf("UnixProgress = %d entering MachUserReturn\n",
  1298.         procPtr->unixProgress);
  1299.     }
  1300.  
  1301.     /* 
  1302.      * Take a context switch if one is pending for this process.
  1303.      */
  1304.     if (procPtr->schedFlags & SCHED_CONTEXT_SWITCH_PENDING) {
  1305.     Sched_LockAndSwitch();
  1306.     }
  1307.  
  1308.     while (TRUE) {
  1309.     /*
  1310.      * See if we are supposed to single-step this process.  If so
  1311.      * put a break in the proper place.  Don't worry if we miss a signal
  1312.      * because we will be back in real soon anyway (after one instruction).
  1313.      */
  1314.     if (procPtr->genFlags & PROC_SINGLE_STEP_FLAG) {
  1315.         Address        breakPC;
  1316.         unsigned        breakInst;
  1317.         ReturnStatus    status;
  1318.         int            accLen;
  1319.         Address        newAddr;
  1320.  
  1321.         if (machFPCurStatePtr == machCurStatePtr) {
  1322.         MachGetCurFPState(machCurStatePtr);
  1323.         }
  1324.         Vm_MakeAccessible(VM_READONLY_ACCESS, sizeof(Address),
  1325.                   machCurStatePtr->userState.regState.pc, 
  1326.                   &accLen, &newAddr);
  1327.         if (accLen != sizeof(Address)) {
  1328.         printf("MachUserReturn: Can't fetch user's trap PC\n");
  1329.         break;
  1330.         }
  1331.         breakPC = (Address)
  1332.             MachEmulateBranch(machCurStatePtr->userState.regState.regs,
  1333.                       machCurStatePtr->userState.regState.pc,
  1334.                  machCurStatePtr->userState.regState.fpStatusReg,
  1335.                          TRUE);
  1336.         Vm_MakeUnaccessible(newAddr, sizeof(Address));
  1337.         if (Vm_CopyIn(4, breakPC,
  1338.               (Address)&machCurStatePtr->sstepInst) != SUCCESS) {
  1339.         printf("Bad single-step address\n");
  1340.         } else {
  1341.         breakInst = MACH_SSTEP_VAL | 0xd;
  1342.         Vm_ChangeCodeProt(procPtr, breakPC, 4, TRUE);
  1343.         status = Vm_CopyOut(4, (Address)&breakInst, breakPC);
  1344.         Vm_ChangeCodeProt(procPtr, breakPC, 4, FALSE);
  1345.         Vm_FlushCode(procPtr, breakPC, 4);
  1346.         if (status != SUCCESS) {
  1347.             printf("Bad single-step address\n");
  1348.         }
  1349.         }
  1350.         procPtr->genFlags &= ~PROC_SINGLE_STEP_FLAG;
  1351.         Mach_DisableIntr();
  1352.         break;
  1353.     } else {
  1354.         if (procPtr->unixProgress == PROC_PROGRESS_RESTART ||
  1355.             procPtr->unixProgress > 0) {
  1356.         /*
  1357.          * If we received a normal signal, we want to restart
  1358.          * the system call when we leave.
  1359.          * If we received a migrate signal, we will get here on
  1360.          * the new machine.
  1361.          */
  1362.  
  1363.         /*
  1364.          * Mangle the PC so we restart the trap after we leave
  1365.          * the kernel.
  1366.          */
  1367.         restarted = 1;
  1368.         if (debugProcStubs) {
  1369.             printf("Restarting system call with progress %d\n",
  1370.                 procPtr->unixProgress);
  1371.         }
  1372.         procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1373.         }
  1374.         /*
  1375.          * Disable interrupts.  Note that we don't use the DISABLE_INTR 
  1376.          * macro because it increments the nesting depth of interrupts
  1377.          * which we don't want because there is an implicit enable
  1378.          * interrupts on rte.
  1379.          */
  1380.         Mach_DisableIntr();
  1381.         if (!Sig_Pending(procPtr)) {
  1382.         break;
  1383.         }
  1384.         Mach_EnableIntr();
  1385.         sigStack.sigStack.contextPtr = &sigStack.sigContext;
  1386.         if (Sig_Handle(procPtr, &sigStack.sigStack, &pc)) {
  1387.         SetupSigHandler(procPtr, &sigStack, pc);
  1388.         Mach_DisableIntr();
  1389.         break;
  1390.         } else {
  1391.         if (procPtr->unixProgress == PROC_PROGRESS_MIG_RESTART ||
  1392.             procPtr->unixProgress == PROC_PROGRESS_RESTART) {
  1393.             restarted = 1;
  1394.             if (debugProcStubs) {
  1395.             printf("No signal action, so we restarted call\n");
  1396.             }
  1397.             procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1398.         } else if (restarted) {
  1399.             printf("No signal, yet we restarted system call!\n");
  1400.         }
  1401.         }
  1402.     }
  1403.     }
  1404.     
  1405.     /*
  1406.      * It is possible for Sig_Handle to mask the migration signal
  1407.      * if a process is not in a state where it can be migrated.
  1408.      * As soon as we return to user mode, though, we will allow migration.
  1409.      */
  1410.     Sig_AllowMigration(procPtr);
  1411.  
  1412.     if (restarted) {
  1413.     if (debugProcStubs) {
  1414.         printf("Moving the PC to restart the system call\n");
  1415.         printf("Our PC = %x\n",
  1416.             machCurStatePtr->userState.regState.pc);
  1417.     }
  1418.     machCurStatePtr->userState.regState.pc -= 4;
  1419.     if (debugProcStubs) {
  1420.         printf("Now our PC = %x\n",
  1421.             machCurStatePtr->userState.regState.pc);
  1422.         printf("V0 was %d and our call was %d\n", 
  1423.             machCurStatePtr->userState.regState.regs[V0],
  1424.             machCurStatePtr->userState.unixRetVal);
  1425.         printf("Our incoming a0-a3 were %x %x %x %x\n", 
  1426.             machCurStatePtr->userState.regState.regs[A0],
  1427.             machCurStatePtr->userState.regState.regs[A1],
  1428.             machCurStatePtr->userState.regState.regs[A2],
  1429.             machCurStatePtr->userState.regState.regs[A3]);
  1430.     }
  1431.     /*
  1432.      * Our V0 and A3 will have been clobbered by the system call, so
  1433.      * we have to restore them.
  1434.      */
  1435.     machCurStatePtr->userState.regState.regs[V0] =
  1436.         machCurStatePtr->userState.savedV0;
  1437.     machCurStatePtr->userState.regState.regs[A3] =
  1438.         machCurStatePtr->userState.savedA3;
  1439.     }
  1440.  
  1441.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1442.         procPtr->unixProgress != PROC_PROGRESS_UNIX) {
  1443.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1444.     if (debugProcStubs) {
  1445.         printf("UnixProgress = %d leaving MachUserReturn!\n",
  1446.             procPtr->unixProgress);
  1447.     }
  1448.     }
  1449.  
  1450.     return(machFPCurStatePtr == machCurStatePtr);
  1451. }
  1452.  
  1453.  
  1454. /*
  1455.  * ----------------------------------------------------------------------------
  1456.  *
  1457.  * Routines to set up and return from signal handlers.
  1458.  *
  1459.  * In order to call a handler four things must be done:
  1460.  *
  1461.  *    1) The current state of the process must be saved so that when
  1462.  *       the handler returns a normal return to user space can occur.
  1463.  *    2) The user stack must be set up so that the signal number and the
  1464.  *       the signal code are passed to the handler.
  1465.  *    3) Things must be set up so that when the handler returns it returns
  1466.  *       back into the kernel so that state can be cleaned up.
  1467.  *    4) The trap stack that was created when the kernel was entered and is
  1468.  *       used to return a process to user space must be modified so that
  1469.  *       the signal handler is called instead of executing the
  1470.  *       normal return.
  1471.  *
  1472.  * The last one is done by simply changing the program counter where the
  1473.  * user process will execute on return to be the address of the signal
  1474.  * handler and the user stack pointer to point to the proper place on
  1475.  * the user stack.  The first three of these are accomplished by 
  1476.  * setting up the user's registers properly.  The return address register is the
  1477.  * return address where the handler will start executing upon return.  But 
  1478.  * this is just the address of a trap instruction that is stored on the stack
  1479.  * below.  Thus when a handler returns it will execute a trap instruction 
  1480.  * and drop back into the kernel. 
  1481.  */
  1482.  
  1483.  
  1484. /*
  1485.  * ----------------------------------------------------------------------------
  1486.  *
  1487.  * SetupSigHandler --
  1488.  *
  1489.  *      Save machine state on the users stack and set up the exception stack
  1490.  *    so that the user will call the signal handler on return. In order to
  1491.  * Results:
  1492.  *      None.
  1493.  *
  1494.  * Side effects:
  1495.  *      Signal stack set up and saved.
  1496.  *
  1497.  * ----------------------------------------------------------------------------
  1498.  */
  1499. static void
  1500. SetupSigHandler(procPtr, sigStackPtr, pc)
  1501.     register    Proc_ControlBlock    *procPtr;
  1502.     register    SignalStack        *sigStackPtr;
  1503.     Address                pc;
  1504. {
  1505.     Mach_UserState    *userStatePtr;
  1506.     unsigned        usp;
  1507.  
  1508.     userStatePtr = &procPtr->machStatePtr->userState;
  1509.     usp = userStatePtr->regState.regs[SP] - sizeof(Sig_Context) - 
  1510.       MACH_STAND_FRAME_SIZE;
  1511.  
  1512.     sigStackPtr->sigContext.machContext.break1Inst = 0x1000d;
  1513.     /*
  1514.      * Copy the user state onto the signal stack.
  1515.      */
  1516.     bcopy((Address)userStatePtr,
  1517.           (Address)&(sigStackPtr->sigContext.machContext.userState),
  1518.           sizeof(Mach_UserState));
  1519.     /*
  1520.      * Copy over the floating point state.
  1521.      */
  1522.     if (machFPCurStatePtr == machCurStatePtr) {
  1523.     MachGetCurFPState(machCurStatePtr);
  1524.     }
  1525.     bcopy((Address)procPtr->machStatePtr->userState.regState.fpRegs,
  1526.       (Address)sigStackPtr->sigContext.machContext.fpRegs,
  1527.       MACH_NUM_FPRS * sizeof(int));
  1528.     sigStackPtr->sigContext.machContext.fpStatusReg =
  1529.             procPtr->machStatePtr->userState.regState.fpStatusReg;
  1530.     /*
  1531.      * Copy the stack out to user space.
  1532.      */
  1533.     if (Vm_CopyOut(sizeof(Sig_Context), (Address)&sigStackPtr->sigContext,
  1534.             (Address)(usp + MACH_STAND_FRAME_SIZE)) != SUCCESS) {
  1535.         printf("Warning: HandleSig: No room on stack for signal, PID=%x.\n",
  1536.                   procPtr->processID);
  1537.         Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1538.     }
  1539.     /*
  1540.      * Now set up the registers correctly.
  1541.      */
  1542.     userStatePtr->regState.regs[SP] = usp;
  1543.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX) {
  1544.     int unixSignal;
  1545.     if (Compat_SpriteSignalToUnix(sigStackPtr->sigStack.sigNum,
  1546.         &unixSignal) != SUCCESS) {
  1547.         printf("Signal %d invalid in SetupSigHandler\n",
  1548.             sigStackPtr->sigStack.sigNum);
  1549.     } else {
  1550.         userStatePtr->regState.regs[A0] = unixSignal;
  1551.     }
  1552.     } else {
  1553.     userStatePtr->regState.regs[A0] = sigStackPtr->sigStack.sigNum;
  1554.     }
  1555.     userStatePtr->regState.regs[A1] = sigStackPtr->sigStack.sigCode;
  1556.     userStatePtr->regState.regs[A2] = usp + MACH_STAND_FRAME_SIZE;
  1557.     userStatePtr->regState.regs[A3] = sigStackPtr->sigStack.sigAddr;
  1558.     userStatePtr->regState.pc = pc;
  1559.     userStatePtr->regState.regs[RA] = usp + MACH_STAND_FRAME_SIZE + 
  1560.         (unsigned)&((Sig_Context *)0)->machContext.break1Inst;
  1561. }
  1562.  
  1563.  
  1564. /*
  1565.  * ----------------------------------------------------------------------------
  1566.  *
  1567.  * ReturnFromSigHandler --
  1568.  *
  1569.  *      Process a return from a signal handler.
  1570.  *    
  1571.  * Results:
  1572.  *      None.
  1573.  *
  1574.  * Side effects:
  1575.  *      Signal stack struct and size filled in the machine struct for the
  1576.  *    given process.
  1577.  *
  1578.  * ----------------------------------------------------------------------------
  1579.  */
  1580. static void
  1581. ReturnFromSigHandler(procPtr)
  1582.     register    Proc_ControlBlock    *procPtr;
  1583. {
  1584.     register    Mach_State    *statePtr;
  1585.     SignalStack            sigStack;
  1586.  
  1587.     statePtr = procPtr->machStatePtr;
  1588.     /*
  1589.      * Copy the signal stack in.
  1590.      */
  1591.     if (Vm_CopyIn(sizeof(Sig_Context),
  1592.           (Address)(statePtr->userState.regState.regs[SP] + 
  1593.                 MACH_STAND_FRAME_SIZE),
  1594.           (Address) &sigStack.sigContext) != SUCCESS) {
  1595.     printf("%s Mach_Code: Stack too small to extract trap info, PID=%x.\n",
  1596.         "Warning:", procPtr->processID);
  1597.     Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1598.     }
  1599.     sigStack.sigStack.contextPtr = &sigStack.sigContext;
  1600.     /*
  1601.      * Take the proper action on return from a signal.
  1602.      */
  1603.     Sig_Return(procPtr, &sigStack.sigStack);
  1604.     /*
  1605.      * Restore user state.
  1606.      */
  1607.     bcopy((Address)&sigStack.sigContext.machContext.userState,
  1608.           (Address)&statePtr->userState, sizeof(statePtr->userState));
  1609.     /*
  1610.      * Copy in the floating point state.
  1611.      */
  1612.     bcopy((Address)sigStack.sigContext.machContext.fpRegs,
  1613.       (Address)statePtr->userState.regState.fpRegs,
  1614.       MACH_NUM_FPRS * sizeof(int));
  1615.     statePtr->userState.regState.fpStatusReg = 
  1616.     sigStack.sigContext.machContext.fpStatusReg & ~MACH_FPC_EXCEPTION_BITS;
  1617.     if (machFPCurStatePtr == machCurStatePtr) {
  1618.     machFPCurStatePtr = (Mach_State *)NIL;
  1619.     }
  1620. }
  1621.  
  1622.  
  1623. /*
  1624.  * ----------------------------------------------------------------------------
  1625.  *
  1626.  * Mach_ProcessorState --
  1627.  *
  1628.  *    Determines what state the processor is in.
  1629.  *
  1630.  * Results:
  1631.  *    MACH_USER    if was at user level
  1632.  *    MACH_KERNEL    if was at kernel level
  1633.  *
  1634.  * Side effects:
  1635.  *    None.
  1636.  *
  1637.  * ----------------------------------------------------------------------------
  1638.  */
  1639. /*ARGSUSED*/
  1640. Mach_ProcessorStates 
  1641. Mach_ProcessorState(processor)
  1642.     int processor;    /* processor number for which info is requested */
  1643. {
  1644.     if (mach_KernelMode) {
  1645.     return(MACH_KERNEL);
  1646.     } else {
  1647.     return(MACH_USER);
  1648.     }
  1649. }
  1650.  
  1651.  
  1652. /*
  1653.  * ----------------------------------------------------------------------------
  1654.  *
  1655.  * Mach_GetMachineArch --
  1656.  *
  1657.  *    Return the machine architecture.
  1658.  *
  1659.  * Results:
  1660.  *    The machine architecture.
  1661.  *
  1662.  * Side effects:
  1663.  *    None.
  1664.  *
  1665.  * ----------------------------------------------------------------------------
  1666.  */
  1667. int
  1668. Mach_GetMachineArch()
  1669. {
  1670.     return SYS_DS3100;
  1671. }
  1672.  
  1673.  
  1674. /*
  1675.  * ----------------------------------------------------------------------------
  1676.  *
  1677.  * Mach_GetMachineType --
  1678.  *
  1679.  *    Return the machine type.
  1680.  *
  1681.  * Results:
  1682.  *    0.
  1683.  *
  1684.  * Side effects:
  1685.  *    None.
  1686.  *
  1687.  * ----------------------------------------------------------------------------
  1688.  */
  1689. int
  1690. Mach_GetMachineType()
  1691. {
  1692.     return 0;
  1693. }
  1694.  
  1695.  
  1696. /*
  1697.  * ----------------------------------------------------------------------------
  1698.  *
  1699.  *  Mach_CheckSpecialHandling--
  1700.  *
  1701.  *    Forces a processor to check the special handling flag of a process.
  1702.  *    This should only be called on a multiprocessor.
  1703.  *
  1704.  * Results:
  1705.  *    None.
  1706.  *
  1707.  * Side effects:
  1708.  *    None.
  1709.  *
  1710.  * ----------------------------------------------------------------------------
  1711.  */
  1712. void
  1713. Mach_CheckSpecialHandling(pnum)
  1714.     int        pnum;        /* Processor number. */
  1715. {
  1716.     panic("Mach_CheckSpecialHandling called for processor %d\n",pnum);
  1717. }
  1718.  
  1719.  
  1720. /*
  1721.  *----------------------------------------------------------------------
  1722.  *
  1723.  * Mach_GetNumProcessors() --
  1724.  *
  1725.  *    Return the number of processors in the system.  NOTE: This should
  1726.  *    really be in a machine-independent area of the mach module.  Note
  1727.  *    further: if this is used only as a system call, it should return
  1728.  *    a ReturnStatus!
  1729.  *
  1730.  * Results:
  1731.  *    The number of processors is returned.  
  1732.  *
  1733.  * Side effects:
  1734.  *    None
  1735.  *
  1736.  *----------------------------------------------------------------------
  1737.  */
  1738.  
  1739. int
  1740. Mach_GetNumProcessors()
  1741. {
  1742.     return (mach_NumProcessors);
  1743. }
  1744.  
  1745.  
  1746. /*
  1747.  *----------------------------------------------------------------------
  1748.  *
  1749.  * Mach_GetBootArgs --
  1750.  *
  1751.  *    Returns the arguments out of the boot parameter structure. 
  1752.  *
  1753.  * Results:
  1754.  *    Number of elements returned in argv.
  1755.  *
  1756.  * Side effects:
  1757.  *    None.
  1758.  *
  1759.  *----------------------------------------------------------------------
  1760.  */
  1761. /*ARGSUSED*/
  1762. int
  1763. Mach_GetBootArgs(argc, bufferSize, argv, buffer)
  1764.     int    argc;            /* Number of elements in argv */
  1765.     int    bufferSize;        /* Size of buffer */
  1766.     char    **argv;            /* Ptr to array of arg pointers */
  1767.     char    *buffer;        /* Storage for arguments */
  1768. {
  1769.     int        i;
  1770.     int        offset;
  1771.  
  1772.     bcopy(machMonBootParam.strings, buffer, 
  1773.       (bufferSize < 256) ? bufferSize : 256);
  1774.     offset = (int) machMonBootParam.strings - (int) buffer;
  1775.     for(i = 0; i < argc; i++) {
  1776.     if (machMonBootParam.argPtr[i] == (char *)NULL) break;
  1777.     argv[i] = (char *) (machMonBootParam.argPtr[i] - (char *) offset);
  1778.     }
  1779.     return i;
  1780. }
  1781.  
  1782. /*
  1783.  *----------------------------------------------------------------------
  1784.  *
  1785.  * Mach_GetEtherAddress --
  1786.  *
  1787.  *    Return the ethernet address out of the rom.
  1788.  *
  1789.  * Results:
  1790.  *    Number of elements returned in argv.
  1791.  *
  1792.  * Side effects:
  1793.  *    *etherAddrPtr gets the ethernet address.
  1794.  *
  1795.  *----------------------------------------------------------------------
  1796.  */
  1797. void
  1798. Mach_GetEtherAddress(etherAddrPtr)
  1799.     Net_EtherAddress    *etherAddrPtr;
  1800. {
  1801.     volatile unsigned    *romPtr = (unsigned *)0xBD000000;
  1802.  
  1803.     etherAddrPtr->byte1 = (romPtr[0] >> 8) & 0xff;
  1804.     etherAddrPtr->byte2 = (romPtr[1] >> 8) & 0xff;
  1805.     etherAddrPtr->byte3 = (romPtr[2] >> 8) & 0xff;
  1806.     etherAddrPtr->byte4 = (romPtr[3] >> 8) & 0xff;
  1807.     etherAddrPtr->byte5 = (romPtr[4] >> 8) & 0xff;
  1808.     etherAddrPtr->byte6 = (romPtr[5] >> 8) & 0xff;
  1809. }
  1810.  
  1811.  
  1812. /*
  1813.  *----------------------------------------------------------------------
  1814.  *
  1815.  * MemErrorInterrupt --
  1816.  *
  1817.  *    Handler an interrupt for the DZ device.
  1818.  *
  1819.  * Results:
  1820.  *    None.
  1821.  *
  1822.  * Side effects:
  1823.  *    None.
  1824.  *
  1825.  *----------------------------------------------------------------------
  1826.  */
  1827. static void
  1828. MemErrorInterrupt()
  1829. {
  1830.     unsigned short *sysCSRPtr = (unsigned short *)0xbe000000;
  1831.     unsigned short csr;
  1832.  
  1833.     csr = *sysCSRPtr;
  1834.  
  1835.     if (csr & MACH_CSR_MEM_ERR) {
  1836.     panic("Mem error interrupt\n");
  1837.     } else {
  1838.     *sysCSRPtr = MACH_CSR_VINT | csr | 0x00ff;
  1839.     }
  1840. }
  1841.  
  1842.  
  1843. /*
  1844.  *----------------------------------------------------------------------
  1845.  *
  1846.  * Mach_FlushCode --
  1847.  *
  1848.  *    Flush the kernel code from the icache at the given address.
  1849.  *
  1850.  * Results:
  1851.  *    None.
  1852.  *
  1853.  * Side effects:
  1854.  *    None.
  1855.  *
  1856.  *----------------------------------------------------------------------
  1857.  */
  1858. void
  1859. Mach_FlushCode(addr, len) 
  1860.     Address    addr;
  1861.     unsigned    len;
  1862. {
  1863.     unsigned cacheAddr;
  1864.  
  1865.     cacheAddr = VMMACH_PHYS_UNCACHED_START - machInstCacheSize +  
  1866.         ((unsigned)addr & (machInstCacheSize - 1));
  1867. #ifdef notdef
  1868.     printf("len=%d addr=%x cacheAddr=%x\n", len, addr, cacheAddr);
  1869. #endif
  1870.     MachCleanICache(cacheAddr, len);
  1871. }
  1872.  
  1873.  
  1874. /*
  1875.  *----------------------------------------------------------------------
  1876.  *
  1877.  * Mach_SendSignal
  1878.  *
  1879.  *    Send either an illegal instruction or a floating point exception
  1880.  *    to the current process.
  1881.  *
  1882.  * Results:
  1883.  *    None.
  1884.  *
  1885.  * Side effects:
  1886.  *    None.
  1887.  *
  1888.  *----------------------------------------------------------------------
  1889.  */
  1890. void
  1891. Mach_SendSignal(sigType)
  1892.     int    sigType;
  1893. {
  1894.     Proc_ControlBlock    *procPtr;
  1895.  
  1896.     procPtr = Proc_GetActualProc();
  1897.  
  1898.     printf("Mach_SendSignal: Sending signal\n");
  1899.  
  1900.     switch ((int)sigType) {
  1901.     case MACH_SIGFPE:
  1902.         (void) Sig_Send(SIG_ILL_INST, SIG_FP_EXCEPTION,
  1903.                 procPtr->processID, FALSE, (Address)0);
  1904.         break;
  1905.     case MACH_SIGILL:
  1906.         (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1907.                 procPtr->processID, FALSE, (Address)0);
  1908.         break;
  1909.     default:
  1910.         panic("Mach_SendSignal: Bad signal type\n");
  1911.         break;
  1912.     }
  1913. }
  1914.  
  1915. void
  1916. PrintError()
  1917. {
  1918.     panic("Error on stack\n");
  1919. }
  1920.  
  1921. static void
  1922. PrintInst(pc, inst)
  1923.     unsigned pc;
  1924.     unsigned inst;
  1925. {
  1926.     printf("Emulating 0x%x: 0x%x\n", pc, inst);
  1927. }
  1928.  
  1929. static void
  1930. SoftFPReturn()
  1931. {
  1932.     printf("SoftFPReturn\n");
  1933. }
  1934.  
  1935. /*
  1936.  *----------------------------------------------------------------------
  1937.  *
  1938.  * Mach_SigreturnStub --
  1939.  *
  1940.  *    Procedure to map from Unix sigreturn system call to Sprite.
  1941.  *    On the decstation, this is used for returning from a signal.
  1942.  *    Note: This routine is exactly the same as MachUNIXLongJumpReturn.
  1943.  *    Presumably the other routine will go away as soon as Unix
  1944.  *    compatibility is working.
  1945.  *
  1946.  * Results:
  1947.  *    Error code is returned upon error.  Otherwise SUCCESS is returned.
  1948.  *
  1949.  * Side effects:
  1950.  *    Side effects associated with the system call.
  1951.  *
  1952.  *----------------------------------------------------------------------
  1953.  */
  1954. int
  1955. Mach_SigreturnStub(sigContextPtr)
  1956.     struct sigcontext *sigContextPtr;
  1957. {
  1958.     struct sigcontext    sigContext;
  1959.     Mach_RegState    *regsPtr;
  1960.     int            dummy;
  1961.     ReturnStatus    status;
  1962.     extern Mach_State   *machCurStatePtr;
  1963.  
  1964.     status = Vm_CopyIn(sizeof(struct sigcontext), (Address)sigContextPtr,
  1965.                (Address)&sigContext);
  1966.     if (status != SUCCESS) {
  1967.     return(status);
  1968.     }
  1969.     regsPtr = &machCurStatePtr->userState.regState;
  1970.     regsPtr->pc = (Address)(sigContext.sc_pc - 4);
  1971.     bcopy(sigContext.sc_regs, regsPtr->regs, sizeof(sigContext.sc_regs));
  1972.     regsPtr->mflo = sigContext.sc_mdlo;
  1973.     regsPtr->mfhi = sigContext.sc_mdhi;
  1974.     bcopy(sigContext.sc_fpregs, regsPtr->fpRegs, sizeof(sigContext.sc_fpregs));
  1975.     regsPtr->fpStatusReg = sigContext.sc_fpc_csr;
  1976.     Proc_GetCurrentProc()->sigHoldMask = sigContext.sc_mask;
  1977.     return(SUCCESS);
  1978. }
  1979.